package com.ara.websocket;

import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;

import com.ara.websocket.listener.ConnectCallback;
import com.ara.websocket.listener.WebSocketResultCallback;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by XieXin on 2021/7/5.
 * WebSocket 处理类
 */
public final class XWebSocketHelper {
    private final static String TAG = XWebSocketHelper.class.getSimpleName();

    private static XWebSocketHelper instance;
    private List<WebSocketResultCallback> callbacks;
    private final Handler handler = new Handler();

    /*** 心跳时间间隔 */
    private static final long HEART_BEAT_RATE = 3 * 1000;
    /*** 发送心跳时间 */
    private long sendHeartBeatTime;
    /*** 发送心跳数据 */
    private String sendHeartBeatData;
    /*** 是否手动取消连接 是-true 则停止自动重连 */
    private boolean isManualClose;

    public static XWebSocketHelper getInstance() {
        if (instance == null) {
            synchronized (XWebSocketHelper.class) {
                if (instance == null) instance = new XWebSocketHelper();
            }
        }
        return instance;
    }

    public void init(String serverUrl, String sendHeartBeatData, List<WebSocketResultCallback> callbacks) {
        this.callbacks = callbacks;
        this.sendHeartBeatData = sendHeartBeatData;
        if (TextUtils.isEmpty(sendHeartBeatData)) this.sendHeartBeatData = "isAlive";
        if (callbacks == null) this.callbacks = new ArrayList<>();
        XWebSocketClient.init(serverUrl);
    }

    public void connect() {
        new Thread(() -> {
            isManualClose = false;
            XWebSocketClient.connect(new ConnectCallback() {
                @Override
                public void onConnectSuccess(short status, String msg) {
                    for (WebSocketResultCallback callback : callbacks) {
                        if (callback != null) callback.onConnectSuccess();
                    }
                }

                @Override
                public void onMessage(String msg) {
                    for (WebSocketResultCallback callback : callbacks) {
                        if (callback != null) callback.onWebSocketMessage(msg);
                    }
                }

                @Override
                public void onClose(int code, String reason, boolean remote) {
                    for (WebSocketResultCallback callback : callbacks) {
                        if (callback != null)
                            callback.onWebSocketError(new Exception(
                                    "code: " + code + " reason: " + reason + " remote: " + remote)
                            );
                    }
                }

                @Override
                public void onError(Exception e) {
                    for (WebSocketResultCallback callback : callbacks) {
                        if (callback != null) callback.onWebSocketError(e);
                    }
                }
            });

            //不管是否连接成功开始心跳
            handler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);
            sendHeartBeat();
        }).start();
    }

    /**
     * 发送心跳
     */
    private void sendHeartBeat() {
        sendHeartBeatTime = System.currentTimeMillis();
        send(sendHeartBeatData);
    }

    /**
     * 断开连接
     */
    public void close() {
        isManualClose = true;
        XWebSocketClient.close();
    }

    /**
     * 重连WebSocket
     */
    public void reconnection() {
        isManualClose = false;
        new Thread(XWebSocketClient::reconnection).start();
    }

    /**
     * 是否Client为空
     */
    public boolean isEmpty() {
        return XWebSocketClient.isEmpty();
    }

    /**
     * 是否关闭
     */
    public boolean isClose() {
        return XWebSocketClient.isClose();
    }

    /**
     * 是否连接
     */
    public boolean isOpen() {
        return XWebSocketClient.isOpen();
    }

    /**
     * 发送消息
     *
     * @param message String
     */
    public void send(String message) {
        XWebSocketClient.sendMessage(message);
    }

    /*** 心跳处理 */
    private final Runnable heartBeatRunnable = new Runnable() {
        @Override
        public void run() {
            if (isManualClose) return;//手动取消停止心跳
            //超过心跳时间重新连接
            if (System.currentTimeMillis() - sendHeartBeatTime >= HEART_BEAT_RATE) {
                if (!isEmpty()) {
                    if (isClose() && !isOpen()) {
                        Log.e(TAG, "WebSocket开始重连");
                        reconnection();
                    } else {
                        Log.i(TAG, "WebSocket未关闭，重新发送心跳");
                        sendHeartBeat();
                    }
                } else {
                    Log.e(TAG, "客户端未初始化，重新初始化");
                    connect();
                }
            }
            handler.postDelayed(this, HEART_BEAT_RATE);
        }
    };
}
